package org.zjx.command;

import lombok.Getter;
import org.zjx.command.basic.*;
import org.zjx.command.composite.FindImageCommand;
import org.zjx.command.composite.IdentifyFontCommand;
import org.zjx.command.composite.IdentifyTessCommand;
import org.zjx.core.IWindow;
import org.zjx.enums.FontAttribute;
import org.zjx.state.StateManager;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.List;
import java.util.Map;
import java.util.function.Function;

public class CompositeCommandBuilder {
    // 获取内部命令（用于调试或特殊需求）
    @Getter
    private final CompositeCommand command;
    private final IWindow window;
    private final StateManager stateManager;

    public CompositeCommandBuilder(IWindow window, StateManager stateManager) {
        this.window = window;
        this.stateManager = stateManager;
        this.command = new CompositeCommand(window, stateManager) {
            @Override
            protected void initializeSubCommands() {
                // 空的初始化，由建造者动态构建
            }
        };
    }

    // 基础操作
    public CompositeCommandBuilder move(int x, int y) {
        command.add(new MoveCommand(window, x, y, stateManager));
        return this;
    }

    public CompositeCommandBuilder move(Point point) {
        if (point != null) {
            command.add(new MoveCommand(window, point.x, point.y, stateManager));
        }
        return this;
    }

    public CompositeCommandBuilder click() {
        command.add(new ClickCommand(window, 1, 1));
        return this;
    }

    public CompositeCommandBuilder click(int button, int count) {
        command.add(new ClickCommand(window, button, count));
        return this;
    }

    public CompositeCommandBuilder delay(long ms) {
        command.add(new DelayCommand(window, ms));
        return this;
    }

    public CompositeCommandBuilder write(String text) {
        command.add(new WriteCommand(window, stateManager, text));
        return this;
    }

    public CompositeCommandBuilder key(int... keyCodes) {
        command.add(new KeyCombinationCommand(window, stateManager, keyCodes));
        return this;
    }

    public CompositeCommandBuilder identifyWithFont(Rectangle rectangle, List<Color> colors, FontAttribute fontAttribute, int fontHeight) {
        command.addWithResult(
                new ScreenshotCommand(window),
                "screenshot",
                cmd -> ((ScreenshotCommand) cmd).getScreenshot()
        );

        command.addWithResult(
                new IdentifyFontCommand(window,stateManager,command.get("screenshot"),rectangle,colors,fontAttribute,fontHeight),
                "words",
                cmd -> ((IdentifyFontCommand) cmd).getResult()
        );
        return this;
    }

    public CompositeCommandBuilder identifyWithFont(BufferedImage screenshot,Rectangle rectangle, List<Color> colors, FontAttribute fontAttribute, int fontHeight) {
        command.addWithResult(
                new IdentifyFontCommand(window,stateManager,screenshot,rectangle,colors,fontAttribute,fontHeight),
                "words",
                cmd -> ((IdentifyFontCommand) cmd).getResult()
        );
        return this;
    }

    public CompositeCommandBuilder identifyWithTess(Rectangle rectangle) {
        command.addWithResult(
                new ScreenshotCommand(window),
                "screenshot",
                cmd -> ((ScreenshotCommand) cmd).getScreenshot()
        );

        command.addWithResult(
                new IdentifyTessCommand(window,stateManager,command.get("screenshot"),rectangle),
                "words",
                cmd -> ((IdentifyTessCommand) cmd).getResult()
        );
        return this;
    }

    public CompositeCommandBuilder identifyWithTess(BufferedImage screenshot,Rectangle rectangle) {
        command.addWithResult(
                new IdentifyTessCommand(window,stateManager,screenshot,rectangle),
                "words",
                cmd -> ((IdentifyTessCommand) cmd).getResult()
        );
        return this;
    }

    public CompositeCommandBuilder addDynamic(Function<Map<String, Object>, Command> commandFactory) {
        command.addDynamic(commandFactory);
        return this;
    }

    // 图像查找（不点击）
    public CompositeCommandBuilder find(BufferedImage bufferedImage, Rectangle area, String resultKey) {
        command.addWithResult(
                new ScreenshotCommand(window),
                "screenshot",
                cmd -> ((ScreenshotCommand) cmd).getScreenshot()
        );

        command.addWithResult(
                () -> new FindImageCommand(
                        window,
                        command.get("screenshot"),
                        bufferedImage,
                        area
                ),
                resultKey,
                cmd -> ((FindImageCommand) cmd).getPoint()
        );
        return this;
    }

    // 查找并点击（简化版，内部使用条件判断）
    public CompositeCommandBuilder findAndClick(BufferedImage bufferedImage, Rectangle area, String resultKey) {
        return findAndClick(bufferedImage, area, resultKey, 100);
    }

    public CompositeCommandBuilder findAndClick(BufferedImage bufferedImage, Rectangle area, String resultKey, long waitAfterClick) {
        find(bufferedImage, area, resultKey);

        // 使用新的条件分支来实现点击
        return ifFound(resultKey, (b, context) -> {
            Point point = (Point) context.get(resultKey);
            b.move(point.x, point.y)
                    .click();
            if (waitAfterClick > 0) {
                b.delay(waitAfterClick);
            }
        });
    }

    // 方案3：条件分支 - 使用构建器添加系列指令
    public CompositeCommandBuilder ifFound(String resultKey, FoundAction action) {
        return ifFound(resultKey, action, (b, point) -> {});
    }

    // 完整的条件分支方法，支持 true 和 false 两种情况
    public CompositeCommandBuilder ifFound(String resultKey, FoundAction trueAction, FoundAction falseAction) {
        command.addDynamic(context -> {
            Point point = this.command.get(resultKey);
            if (point != null) {
                CompositeCommandBuilder actionBuilder = new CompositeCommandBuilder(window, stateManager);
                trueAction.execute(actionBuilder, context);
                return actionBuilder.build();
            } else {
                CompositeCommandBuilder actionBuilder = new CompositeCommandBuilder(window, stateManager);
                falseAction.execute(actionBuilder, context);
                return actionBuilder.build();
            }
        });
        return this;
    }

    // 条件分支接口
    @FunctionalInterface
    public interface FoundAction {
        void execute(CompositeCommandBuilder builder, Map<String, Object> context);
    }

    public CompositeCommand build() {
        return command;
    }
}